package com.thiswhyme.swagger.servicezuul.config;

import com.google.common.base.Optional;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Documentation;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.DocumentationCache;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Created by thiswhyme on 2019-11-15.
 */
@EnableSwagger2
@Configuration
public class Swagger2Config {

    private static final String DEFAULT_TOKEN = "默认token";

    @Resource
    private Docket docket;

    private final String swagger2Url;

    @Resource
    private DocumentationCache documentationCache;

    private final Environment environment;

    public Swagger2Config(Environment environment) {
        swagger2Url = environment.getProperty("springfox.documentation.swagger.v2.path", "/v2/api-docs");
        this.environment = environment;
    }

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.thiswhyme.swagger.servicezuul.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("SERVICE TWO")
                .description("SWAGGER DEMO")
                .termsOfServiceUrl("http://")
                .contact(new Contact("thiswhyme", "", "thiswhyme@126.com"))
                .version("0.1")
                .build();
    }

    @Bean
    public void swaggerConf() {
        ParameterBuilder ticketPar = new ParameterBuilder();
        List<Parameter> pars = new ArrayList<Parameter>();
        ticketPar.name("Authorization")
                .description("登录校验")
                .modelRef(new ModelRef("string"))
                .parameterType("header").required(false).defaultValue(DEFAULT_TOKEN)
                .build();
        pars.add(ticketPar.build());
        docket.globalOperationParameters(pars);
    }

    @Bean("swaggerResourcesProvider")
    @Primary
    public SwaggerResourcesProvider swaggerResourcesProvider() {
        return () -> {
            List<SwaggerResource> resources = new ArrayList<>();
            for (Map.Entry<String, Documentation> entry : documentationCache.all().entrySet()) {
                String swaggerGroup = entry.getKey();
                SwaggerResource swaggerResource = resource(swaggerGroup, swagger2Url);
                swaggerResource.setSwaggerVersion("2.0");
                resources.add(swaggerResource);
            }
            Collections.sort(resources);
            resources.add(createResource("服务1", "/service-one"));
            resources.add(createResource("服务2", "/service-two"));
            return resources;
        };
    }

    private SwaggerResource createResource(String name, String location) {
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location + "/v2/api-docs");
        swaggerResource.setSwaggerVersion("2.0");
        return swaggerResource;
    }


    private SwaggerResource resource(String swaggerGroup, String baseUrl) {
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(swaggerGroup);
        swaggerResource.setUrl(swaggerLocation(baseUrl, swaggerGroup));
        return swaggerResource;
    }

    private String swaggerLocation(String swaggerUrl, String swaggerGroup) {
        String base = Optional.of(swaggerUrl).get();
        if (Docket.DEFAULT_GROUP_NAME.equals(swaggerGroup)) {
            return base;
        }
        return base + "?group=" + swaggerGroup;
    }
}
